package com.cuiweiyou.pipixiaautomator;

import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.GestureDescription;
import android.graphics.Path;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class PiixaAcsblityService extends AccessibilityService {

    private AccessibilityNodeInfo activeWindow;
    private long diffTime;
    private long lastTime;
    private int centerScreenHeight;
    private int screenHeigth;
    private boolean isPlaying = false;
    private int topBarAndBottomBarHeight = 200;// 标签栏和底部tab的高度。视手机而定
    private String commentVideoId = "com.sup.android.superb:id/feedui_cell_part_god_comment_video_cover"; // 神评视频控件id
    private String contentVideoId = "com.sup.android.superb:id/feedui_cell_video_content"; // 常规视频控件id
    private String bufferProcessBarViewId = "com.sup.android.superb:id/buffer_progress"; // 缓冲按钮
    private String playProcessBarViewId = "com.sup.android.superb:id/play_progress"; // 重播按钮
    private String replayViewId = "com.sup.android.superb:id/iv_video_replay"; // 播放进度条
    private String playViewId = "com.sup.android.superb:id/iv_btn_play"; // 播放按钮

    @Override
    public void onServiceConnected() {
        Log.e("ard", "PiixaAcsblityService启动了");

        diffTime = System.currentTimeMillis();

        DisplayMetrics dm = getApplicationContext().getResources().getDisplayMetrics();
        screenHeigth = dm.heightPixels;
        centerScreenHeight = screenHeigth / 2;

        Log.e("ard", "屏幕高" + screenHeigth + "，垂直中心：" + centerScreenHeight);
    }

    @Override
    public void onAccessibilityEvent(AccessibilityEvent e) {
        CharSequence packageName = e.getPackageName();
        //Log.e("ard", "此事件来自应用：" + packageName);

        int eventType = e.getEventType();
        if (AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED != eventType && AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED != eventType) {
            return;
        }

        long nowTime = System.currentTimeMillis();
        diffTime = nowTime - lastTime;
        if (diffTime < 2000) {
            return;
        }
        lastTime = nowTime;

        Log.e("ard", "PiixaAcsblityService有事件发生：" + isPlaying);

        activeWindow = getRootInActiveWindow();
        if (null == activeWindow) {
            return;
        }

        Log.e("ard", "RootInActiveWindow可用");

        startEvent(); // 系统事件
    }

    private void startEvent() {
        boolean recommendOrVideoInHomePage = isRecommendOrVideoInHomePage();
        if (!recommendOrVideoInHomePage) {
            return;
        }

        boolean replay = findReplayButton();
        boolean playProcessBar = findPlayProcessBar();
        boolean bufferProcessBar = findBufferProcessBar();
        AccessibilityNodeInfo play = findPlayButton();
        AccessibilityNodeInfo video = findVideoElement();
        Log.e("ard", "有视频：" + (null != video));

        if (isPlaying) {
            if (replay) {
                Log.e("ard", "有重播，滑动屏幕吧+++");
                isPlaying = false;
            } else {
                startEvent(); // 播放中检测
                Log.e("ard", "正在播放---0000");

                return;
            }
        }

        if (!isPlaying) {
            if (playProcessBar) {
                Log.e("ard", "正在播放---111");
                isPlaying = true;
                return;
            }

            if (bufferProcessBar) {
                Log.e("ard", "正在缓冲>>>>>>>");
                isPlaying = true;
                return;
            }

            if (null != play) {
                Log.e("ard", "可播放，开始点击播放吧===");
                isPlaying = true;
                playVideo(play);
                return;
            }

            scrollScreen();
        }
    }

    private void playVideo(final AccessibilityNodeInfo play) {
        final Rect bound = new Rect();
        play.getBoundsInScreen(bound);

        clickWidget(bound);
    }

    private void scrollScreen() {
        Log.e("ard", "滑动屏幕。。。");
        int x = 200;
        int range = 100; // 手机滑动距离
        int rdiff = new Random().nextInt(30) + 40;
        int startY = screenHeigth - topBarAndBottomBarHeight - rdiff;
        rdiff = new Random().nextInt(20) + 30;
        int endY = startY - range - rdiff;

        Path path = new Path();  // 手指从屏幕底部向上滑动
        path.moveTo(x, startY);  // 起始点，大于结束点
        path.lineTo(x, endY);    // 结束点

        doDispatchGesture(// 滑动屏幕
                          0, //
                          path,   //
                          "滑动屏幕", //
                          new DispatchGestureListener() {
                              @Override
                              public void dispatchGestureFinish() {
                                  startEvent(); // 滑动屏幕结束
                              }
                          }); //
    }

    private void clickWidget(Rect bound) {

        String note = "点击播放按钮";

        int x = bound.centerX();
        int y = bound.centerY();

        Log.e("ard", note + "，x：" + x + "，y：" + y);

        Path path = new Path();
        path.moveTo(x, y);

        doDispatchGesture(1, path, note, null); // 点击控件
    }

    /**
     * 模拟手势
     *
     * @param flag     0-滑动屏幕，1-点击控件
     * @param path
     * @param note
     * @param listener
     */
    private void doDispatchGesture(final int flag, final Path path, final String note, final DispatchGestureListener listener) {
        GestureDescription.StrokeDescription sd = new GestureDescription.StrokeDescription(path, 5, 200);

        GestureDescription.Builder builder = new GestureDescription.Builder();
        GestureDescription gestureDescription = builder.addStroke(sd).build();

        boolean did = dispatchGesture(//
                                      gestureDescription, //
                                      new AccessibilityService.GestureResultCallback() {
                                          @Override
                                          public void onCompleted(GestureDescription gd) {
                                              super.onCompleted(gd);
                                              Log.e("ard", note + "--手势结束");
                                              if (null != listener) {

                                                  try {
                                                      Thread.sleep(200);
                                                  } catch (InterruptedException e) {
                                                      e.printStackTrace();
                                                  }

                                                  listener.dispatchGestureFinish();
                                              }
                                          }

                                          @Override
                                          public void onCancelled(GestureDescription gestureDescription) {
                                              super.onCancelled(gestureDescription);
                                              Log.e("ard", note + "--手势取消");

                                              try {
                                                  Thread.sleep(200);
                                              } catch (InterruptedException e) {
                                                  e.printStackTrace();
                                              }

                                              if (0 == flag) {
                                                  doDispatchGesture(flag, path, note, listener); // 滑动屏幕时，事件取消了
                                                  return;
                                              }

                                              if (null != listener) {
                                                  listener.dispatchGestureFinish();
                                              }
                                          }
                                      }, //
                                      null);
        Log.e("ard", note + " 是否执行了：" + did);
    }

    private AccessibilityNodeInfo findPlayButton() {
        if (null == activeWindow) {
            Log.e("ard", "Play直接没有window");
            return null;
        }

        List<AccessibilityNodeInfo> playList = activeWindow.findAccessibilityNodeInfosByViewId(playViewId);
        if (null == playList || playList.size() < 1) {
            Log.e("ard", "没有播放按钮");
            activeWindow.refresh();
            return null;
        }

        List<AccessibilityNodeInfo> tmp = new ArrayList<>();
        for (int i = 0; i < playList.size(); i++) {
            AccessibilityNodeInfo ele = playList.get(i);
            Rect bound = new Rect();
            ele.getBoundsInScreen(bound);
            int centerY = bound.centerY();
            int top = screenHeigth / 5 * 2;
            int bottom = screenHeigth / 5 * 3;
            if (centerY < top || centerY > bottom) {
                continue;
            }

            tmp.add(ele);
        }

        if (tmp.size() < 1) {
            Log.e("ard", "没有合格播放按钮");
            return null;
        }

        AccessibilityNodeInfo result = getBestWidget(tmp);

        if (null != result) {
            Rect bound = new Rect();
            result.getBoundsInScreen(bound);

            Log.e("ard", "有合格缓冲进度条，位置：" + bound.centerY());
        }

        return result;
    }

    private boolean findReplayButton() {
        if (null == activeWindow) {
            Log.e("ard", "Replay直接没有window");
            return false;
        }

        List<AccessibilityNodeInfo> replayList = activeWindow.findAccessibilityNodeInfosByViewId(replayViewId);
        if (null == replayList || replayList.size() < 1) {
            replayList = activeWindow.findAccessibilityNodeInfosByText("重播");
        }

        if (null == replayList || replayList.size() < 1) {
            Log.e("ard", "没有重播按钮");
            activeWindow.refresh();
            return false;
        }

        List<AccessibilityNodeInfo> tmp = new ArrayList<>();
        for (int i = 0; i < replayList.size(); i++) {
            AccessibilityNodeInfo ele = replayList.get(i);
            Rect bound = new Rect();
            ele.getBoundsInScreen(bound);
            int centerY = bound.centerY();
            if (centerY < topBarAndBottomBarHeight || centerY > screenHeigth - topBarAndBottomBarHeight) {
                continue;
            }

            tmp.add(ele);
        }

        if (tmp.size() < 1) {
            Log.e("ard", "没有合格重播按钮");
            return false;
        }

        Rect bound = new Rect();
        tmp.get(0).getBoundsInScreen(bound);

        Log.e("ard", "有合格 重播 进度条，位置：" + bound.centerY());

        return true;
    }

    private boolean findBufferProcessBar() {
        if (null == activeWindow) {
            Log.e("ard", "BufferProcessBar直接没有window");
            return false;
        }

        List<AccessibilityNodeInfo> bufferProcessList = activeWindow.findAccessibilityNodeInfosByViewId(bufferProcessBarViewId);
        if (null == bufferProcessList || bufferProcessList.size() < 1) {
            Log.e("ard", "没有缓冲进度条");
            activeWindow.refresh();
            return false;
        }

        List<AccessibilityNodeInfo> tmp = new ArrayList<>();
        for (int i = 0; i < bufferProcessList.size(); i++) {
            AccessibilityNodeInfo ele = bufferProcessList.get(i);
            Rect bound = new Rect();
            ele.getBoundsInScreen(bound);
            int centerY = bound.centerY();
            int top = screenHeigth / 5 * 2;
            int bottom = screenHeigth / 5 * 3;
            if (centerY < top || centerY > bottom) {
                continue;
            }

            tmp.add(ele);
        }

        if (tmp.size() < 1) {
            Log.e("ard", "没有合格缓冲进度条");
            return false;
        }

        Rect bound = new Rect();
        tmp.get(0).getBoundsInScreen(bound);

        Log.e("ard", "有合格缓冲进度条，位置：" + bound.centerY());

        return true;
    }

    private boolean findPlayProcessBar() {
        if (null == activeWindow) {
            Log.e("ard", "PlayProcessBar直接没有window");
            return false;
        }

        List<AccessibilityNodeInfo> playProcessList = activeWindow.findAccessibilityNodeInfosByViewId(playProcessBarViewId);
        if (null == playProcessList || playProcessList.size() < 1) {
            Log.e("ard", "没有播放进度条");
            activeWindow.refresh();
            return false;
        }

        List<AccessibilityNodeInfo> tmp = new ArrayList<>();
        for (int i = 0; i < playProcessList.size(); i++) {
            AccessibilityNodeInfo ele = playProcessList.get(i);
            Rect bound = new Rect();
            ele.getBoundsInScreen(bound);
            int centerY = bound.centerY();
            int diff = (centerScreenHeight - topBarAndBottomBarHeight) / 4;
            int top = centerScreenHeight + diff;
            int bottom = screenHeigth - topBarAndBottomBarHeight - diff;
            if (centerY < top || centerY > bottom) {
                continue;
            }

            tmp.add(ele);
        }

        if (tmp.size() < 1) {
            Log.e("ard", "没有合格播放进度条");
            return false;
        }

        Rect bound = new Rect();
        tmp.get(0).getBoundsInScreen(bound);

        Log.e("ard", "有合格播放进度条，位置：" + bound.centerY());

        return true;
    }

    private AccessibilityNodeInfo findVideoElement() {
        AccessibilityNodeInfo video = filterVideoElements(contentVideoId);
        if (null == video) {

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // video = filterVideoElements(commentVideoId);
        }
        return video;
    }

    private AccessibilityNodeInfo filterVideoElements(String viewId) {
        if (null == activeWindow) {
            Log.e("ard", "NodeInfo直接没有window");
            return null;
        }

        List<AccessibilityNodeInfo> elements = activeWindow.findAccessibilityNodeInfosByViewId(viewId);
        if (null == elements || elements.size() < 1) {
            Log.e("ard", "直接没有视频控件");
            activeWindow.refresh();
            return null;
        }

        List<AccessibilityNodeInfo> tmp = new ArrayList<>();
        for (int i = 0; i < elements.size(); i++) {
            AccessibilityNodeInfo ele = elements.get(i);
            Rect bound = new Rect();
            ele.getBoundsInScreen(bound);
            int centerY = bound.centerY();
            if (centerY < topBarAndBottomBarHeight || centerY > screenHeigth - topBarAndBottomBarHeight) {
                continue;
            }

            tmp.add(ele);
        }

        if (tmp.size() < 1) {
            Log.e("ard", "没有合格视频控件");
            return null;
        }

        AccessibilityNodeInfo result = getBestWidget(tmp);

        Rect rect = new Rect();
        result.getBoundsInScreen(rect);
        int x = rect.centerX();
        int y = rect.centerY();
        Log.e("ard", "可用视频控件 x=" + x + "，y=" + y);

        return result;
    }

    private AccessibilityNodeInfo getBestWidget(List<AccessibilityNodeInfo> tmp) {
        AccessibilityNodeInfo result = tmp.get(0);
        Rect boundResult = new Rect();
        result.getBoundsInScreen(boundResult);
        int centerYResult = boundResult.centerY();
        int diffY = Math.abs(centerYResult - centerScreenHeight);
        for (int i = 1; i < tmp.size(); i++) {
            AccessibilityNodeInfo node = tmp.get(i);
            Rect boundTmp = new Rect();
            node.getBoundsInScreen(boundTmp);
            int centerYTmp = boundTmp.centerY();
            int diffYTmp = Math.abs(centerYTmp - centerScreenHeight);
            if (diffYTmp < diffY) {
                diffY = diffYTmp;
                result = node;
            }
        }

        return result;
    }

    private boolean isRecommendOrVideoInHomePage() {
        boolean result = false;

        result = checkHomePage("首页", "刷新");
        if (result) {
            result = checkLabelPage("推荐", "视频");
        }

        return result;
    }

    private boolean checkHomePage(String pageName1, String pageName2) {
        List<AccessibilityNodeInfo> pageList = activeWindow.findAccessibilityNodeInfosByText(pageName1);
        if (null == pageList || pageList.size() < 1) {
            pageList = activeWindow.findAccessibilityNodeInfosByText(pageName2);
            Log.e("ard", "没有在" + pageName1 + "页");
            if (null == pageList || pageList.size() < 1) {
                Log.e("ard", "没有在" + pageName2 + "页");
                return false;
            }
        }

        AccessibilityNodeInfo node = pageList.get(0); // 皮皮虾的相关便签只有一个，所以不轮训了
        boolean selected = node.isSelected();
        if (!selected) {
            Log.e("ard", "没有在" + pageName1 + "页也没有在" + pageName2 + "页");
            return false;
        }

        return true;
    }

    /*
     * 这里没用 isSelected 进行判断，因为在开发设备上6个标签选中与否都是false。只好根据面积判断
     * todo 不同手机一定是不一致的 [443, 92]  [547,159]
     */
    private boolean checkLabelPage(String labelName1, String labelName2) {
        List<AccessibilityNodeInfo> labelList = activeWindow.findAccessibilityNodeInfosByViewId("com.sup.android.superb:id/category_text");
        if (null == labelList || labelList.size() < 1) {
            Log.e("ard", "没有在皮皮虾标签页");
            return false;
        }

        int selectedArea = 74 * 67;

        for (int i = 0; i < labelList.size(); i++) {
            AccessibilityNodeInfo label = labelList.get(i);

            Rect bound = new Rect();
            label.getBoundsInScreen(bound);
            int width = bound.width();
            int height = bound.height();
            int area = width * height;
            int compare = Integer.compare(area, selectedArea);

            if (compare >= 0) {
                CharSequence name = label.getText();
                if (name.equals(labelName1) || name.equals(labelName2)) {
                    Log.e("ard", "当前在 " + name + " 标签");
                    return true;
                }
            }
        }

        Log.e("ard", "没有推荐和视频标签");

        return false;
    }

    @Override
    public void onInterrupt() {
        Log.e("ard", "PiixaAcsblityService终止了");
    }

    interface DispatchGestureListener {
        void dispatchGestureFinish();
    }
}
